home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / CGIHTTPServer.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  10KB  |  371 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. """CGI-savvy HTTP Server.
  5.  
  6. This module builds on SimpleHTTPServer by implementing GET and POST
  7. requests to cgi-bin scripts.
  8.  
  9. If the os.fork() function is not present (e.g. on Windows),
  10. os.popen2() is used as a fallback, with slightly altered semantics; if
  11. that function is not present either (e.g. on Macintosh), only Python
  12. scripts are supported, and they are executed by the current process.
  13.  
  14. In all cases, the implementation is intentionally naive -- all
  15. requests are executed sychronously.
  16.  
  17. SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
  18. -- it may execute arbitrary Python code or external programs.
  19.  
  20. """
  21. __version__ = '0.4'
  22. __all__ = [
  23.     'CGIHTTPRequestHandler']
  24. import os
  25. import sys
  26. import urllib
  27. import BaseHTTPServer
  28. import SimpleHTTPServer
  29. import select
  30.  
  31. class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  32.     '''Complete HTTP server with GET, HEAD and POST commands.
  33.  
  34.     GET and HEAD also support running CGI scripts.
  35.  
  36.     The POST command is *only* implemented for CGI scripts.
  37.  
  38.     '''
  39.     have_fork = hasattr(os, 'fork')
  40.     have_popen2 = hasattr(os, 'popen2')
  41.     have_popen3 = hasattr(os, 'popen3')
  42.     rbufsize = 0
  43.     
  44.     def do_POST(self):
  45.         '''Serve a POST request.
  46.  
  47.         This is only implemented for CGI scripts.
  48.  
  49.         '''
  50.         if self.is_cgi():
  51.             self.run_cgi()
  52.         else:
  53.             self.send_error(501, 'Can only POST to CGI scripts')
  54.  
  55.     
  56.     def send_head(self):
  57.         '''Version of send_head that support CGI scripts'''
  58.         if self.is_cgi():
  59.             return self.run_cgi()
  60.         else:
  61.             return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
  62.  
  63.     
  64.     def is_cgi(self):
  65.         """Test whether self.path corresponds to a CGI script.
  66.  
  67.         Return a tuple (dir, rest) if self.path requires running a
  68.         CGI script, None if not.  Note that rest begins with a
  69.         slash if it is not empty.
  70.  
  71.         The default implementation tests whether the path
  72.         begins with one of the strings in the list
  73.         self.cgi_directories (and the next character is a '/'
  74.         or the end of the string).
  75.  
  76.         """
  77.         path = self.path
  78.         for x in self.cgi_directories:
  79.             i = len(x)
  80.             if path[:i] == x:
  81.                 if not path[i:] or path[i] == '/':
  82.                     self.cgi_info = (path[:i], path[i + 1:])
  83.                     return True
  84.                     continue
  85.         
  86.         return False
  87.  
  88.     cgi_directories = [
  89.         '/cgi-bin',
  90.         '/htbin']
  91.     
  92.     def is_executable(self, path):
  93.         '''Test whether argument path is an executable file.'''
  94.         return executable(path)
  95.  
  96.     
  97.     def is_python(self, path):
  98.         '''Test whether argument path is a Python script.'''
  99.         (head, tail) = os.path.splitext(path)
  100.         return tail.lower() in ('.py', '.pyw')
  101.  
  102.     
  103.     def run_cgi(self):
  104.         '''Execute a CGI script.'''
  105.         (dir, rest) = self.cgi_info
  106.         i = rest.rfind('?')
  107.         if i >= 0:
  108.             rest = rest[:i]
  109.             query = rest[i + 1:]
  110.         else:
  111.             query = ''
  112.         i = rest.find('/')
  113.         if i >= 0:
  114.             script = rest[:i]
  115.             rest = rest[i:]
  116.         else:
  117.             script = rest
  118.             rest = ''
  119.         scriptname = dir + '/' + script
  120.         scriptfile = self.translate_path(scriptname)
  121.         if not os.path.exists(scriptfile):
  122.             self.send_error(404, 'No such CGI script (%r)' % scriptname)
  123.             return None
  124.         
  125.         if not os.path.isfile(scriptfile):
  126.             self.send_error(403, 'CGI script is not a plain file (%r)' % scriptname)
  127.             return None
  128.         
  129.         ispy = self.is_python(scriptname)
  130.         if not ispy:
  131.             if not self.have_fork and self.have_popen2 or self.have_popen3:
  132.                 self.send_error(403, 'CGI script is not a Python script (%r)' % scriptname)
  133.                 return None
  134.             
  135.             if not self.is_executable(scriptfile):
  136.                 self.send_error(403, 'CGI script is not executable (%r)' % scriptname)
  137.                 return None
  138.             
  139.         
  140.         env = { }
  141.         env['SERVER_SOFTWARE'] = self.version_string()
  142.         env['SERVER_NAME'] = self.server.server_name
  143.         env['GATEWAY_INTERFACE'] = 'CGI/1.1'
  144.         env['SERVER_PROTOCOL'] = self.protocol_version
  145.         env['SERVER_PORT'] = str(self.server.server_port)
  146.         env['REQUEST_METHOD'] = self.command
  147.         uqrest = urllib.unquote(rest)
  148.         env['PATH_INFO'] = uqrest
  149.         env['PATH_TRANSLATED'] = self.translate_path(uqrest)
  150.         env['SCRIPT_NAME'] = scriptname
  151.         if query:
  152.             env['QUERY_STRING'] = query
  153.         
  154.         host = self.address_string()
  155.         if host != self.client_address[0]:
  156.             env['REMOTE_HOST'] = host
  157.         
  158.         env['REMOTE_ADDR'] = self.client_address[0]
  159.         authorization = self.headers.getheader('authorization')
  160.         if authorization:
  161.             authorization = authorization.split()
  162.             if len(authorization) == 2:
  163.                 import base64 as base64
  164.                 import binascii as binascii
  165.                 env['AUTH_TYPE'] = authorization[0]
  166.                 if authorization[0].lower() == 'basic':
  167.                     
  168.                     try:
  169.                         authorization = base64.decodestring(authorization[1])
  170.                     except binascii.Error:
  171.                         pass
  172.  
  173.                     authorization = authorization.split(':')
  174.                     if len(authorization) == 2:
  175.                         env['REMOTE_USER'] = authorization[0]
  176.                     
  177.                 
  178.             
  179.         
  180.         if self.headers.typeheader is None:
  181.             env['CONTENT_TYPE'] = self.headers.type
  182.         else:
  183.             env['CONTENT_TYPE'] = self.headers.typeheader
  184.         length = self.headers.getheader('content-length')
  185.         if length:
  186.             env['CONTENT_LENGTH'] = length
  187.         
  188.         accept = []
  189.         for line in self.headers.getallmatchingheaders('accept'):
  190.             if line[:1] in '\t\n\r ':
  191.                 accept.append(line.strip())
  192.                 continue
  193.             accept = accept + line[7:].split(',')
  194.         
  195.         env['HTTP_ACCEPT'] = ','.join(accept)
  196.         ua = self.headers.getheader('user-agent')
  197.         if ua:
  198.             env['HTTP_USER_AGENT'] = ua
  199.         
  200.         co = filter(None, self.headers.getheaders('cookie'))
  201.         if co:
  202.             env['HTTP_COOKIE'] = ', '.join(co)
  203.         
  204.         for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', 'HTTP_USER_AGENT', 'HTTP_COOKIE'):
  205.             env.setdefault(k, '')
  206.         
  207.         os.environ.update(env)
  208.         self.send_response(200, 'Script output follows')
  209.         decoded_query = query.replace('+', ' ')
  210.         if self.have_fork:
  211.             args = [
  212.                 script]
  213.             if '=' not in decoded_query:
  214.                 args.append(decoded_query)
  215.             
  216.             nobody = nobody_uid()
  217.             self.wfile.flush()
  218.             pid = os.fork()
  219.             if pid != 0:
  220.                 (pid, sts) = os.waitpid(pid, 0)
  221.                 while select.select([
  222.                     self.rfile], [], [], 0)[0]:
  223.                     if not self.rfile.read(1):
  224.                         break
  225.                         continue
  226.                 if sts:
  227.                     self.log_error('CGI script exit status %#x', sts)
  228.                 
  229.                 return None
  230.             
  231.             
  232.             try:
  233.                 
  234.                 try:
  235.                     os.setuid(nobody)
  236.                 except os.error:
  237.                     pass
  238.  
  239.                 os.dup2(self.rfile.fileno(), 0)
  240.                 os.dup2(self.wfile.fileno(), 1)
  241.                 os.execve(scriptfile, args, os.environ)
  242.             self.server.handle_error(self.request, self.client_address)
  243.             os._exit(127)
  244.  
  245.         elif self.have_popen2 or self.have_popen3:
  246.             import shutil as shutil
  247.             if self.have_popen3:
  248.                 popenx = os.popen3
  249.             else:
  250.                 popenx = os.popen2
  251.             cmdline = scriptfile
  252.             if self.is_python(scriptfile):
  253.                 interp = sys.executable
  254.                 if interp.lower().endswith('w.exe'):
  255.                     interp = interp[:-5] + interp[-4:]
  256.                 
  257.                 cmdline = '%s -u %s' % (interp, cmdline)
  258.             
  259.             if '=' not in query and '"' not in query:
  260.                 cmdline = '%s "%s"' % (cmdline, query)
  261.             
  262.             self.log_message('command: %s', cmdline)
  263.             
  264.             try:
  265.                 nbytes = int(length)
  266.             except (TypeError, ValueError):
  267.                 nbytes = 0
  268.  
  269.             files = popenx(cmdline, 'b')
  270.             fi = files[0]
  271.             fo = files[1]
  272.             if self.have_popen3:
  273.                 fe = files[2]
  274.             
  275.             if self.command.lower() == 'post' and nbytes > 0:
  276.                 data = self.rfile.read(nbytes)
  277.                 fi.write(data)
  278.             
  279.             while select.select([
  280.                 self.rfile._sock], [], [], 0)[0]:
  281.                 if not self.rfile._sock.recv(1):
  282.                     break
  283.                     continue
  284.             fi.close()
  285.             shutil.copyfileobj(fo, self.wfile)
  286.             if self.have_popen3:
  287.                 errors = fe.read()
  288.                 fe.close()
  289.                 if errors:
  290.                     self.log_error('%s', errors)
  291.                 
  292.             
  293.             sts = fo.close()
  294.             if sts:
  295.                 self.log_error('CGI script exit status %#x', sts)
  296.             else:
  297.                 self.log_message('CGI script exited OK')
  298.         else:
  299.             save_argv = sys.argv
  300.             save_stdin = sys.stdin
  301.             save_stdout = sys.stdout
  302.             save_stderr = sys.stderr
  303.             
  304.             try:
  305.                 save_cwd = os.getcwd()
  306.                 
  307.                 try:
  308.                     sys.argv = [
  309.                         scriptfile]
  310.                     if '=' not in decoded_query:
  311.                         sys.argv.append(decoded_query)
  312.                     
  313.                     sys.stdout = self.wfile
  314.                     sys.stdin = self.rfile
  315.                     execfile(scriptfile, {
  316.                         '__name__': '__main__' })
  317.                 finally:
  318.                     sys.argv = save_argv
  319.                     sys.stdin = save_stdin
  320.                     sys.stdout = save_stdout
  321.                     sys.stderr = save_stderr
  322.                     os.chdir(save_cwd)
  323.  
  324.             except SystemExit:
  325.                 sts = None
  326.                 self.log_error('CGI script exit status %s', str(sts))
  327.  
  328.             self.log_message('CGI script exited OK')
  329.  
  330.  
  331. nobody = None
  332.  
  333. def nobody_uid():
  334.     """Internal routine to get nobody's uid"""
  335.     global nobody
  336.     if nobody:
  337.         return nobody
  338.     
  339.     
  340.     try:
  341.         import pwd as pwd
  342.     except ImportError:
  343.         return -1
  344.  
  345.     
  346.     try:
  347.         nobody = pwd.getpwnam('nobody')[2]
  348.     except KeyError:
  349.         nobody = 1 + max(map((lambda x: x[2]), pwd.getpwall()))
  350.  
  351.     return nobody
  352.  
  353.  
  354. def executable(path):
  355.     '''Test for executable file.'''
  356.     
  357.     try:
  358.         st = os.stat(path)
  359.     except os.error:
  360.         return False
  361.  
  362.     return st.st_mode & 73 != 0
  363.  
  364.  
  365. def test(HandlerClass = CGIHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer):
  366.     SimpleHTTPServer.test(HandlerClass, ServerClass)
  367.  
  368. if __name__ == '__main__':
  369.     test()
  370.  
  371.